package uno;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.IOException;
import java.util.LinkedList;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.WindowConstants;

import uno.component.ColorViewer;
import uno.component.Deck;
import uno.component.HandOfCard;
import uno.component.PlayedCardsList;
import uno.component.UnoGraphicPlayerList;
import uno.component.UnoMenuBar;
import uno.net.UnoPlayerID;


public class Main extends JFrame{


	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 7164596278712679124L;
	
	/**
	 * colore corrente
	 * */
	public static String globalCurrentColor;
	
	/**
	 * */
	private JPanel contentPane;
	
	/**
	 * Pannello contenente gli oggetti a sinistra della barra(JSplitPane)
	 * */
	private JPanel leftPanel;
	public JPanel getLeftPanel() { return leftPanel; }

	/**
	 * Pannello contenente gli oggetti a destra della barra(JSplitPane)
	 * */
	private JPanel rightPanel;
	public JPanel getRightPanel() { return rightPanel; }
	
	/**
	 * Pannello che contiene i due mazzi
	 * */
	private JPanel decksContainer;
	public JPanel getDecksContainer() { return decksContainer; }
	
	/**
	 * Pannello separatore - splitter
	 */
	private JSplitPane jSplitPane;
	public JSplitPane getJSplitPane() { return jSplitPane; }
	public void setJSplitPane(JSplitPane givenJSP) { jSplitPane = givenJSP; } 
	
	/**
	 * Lista dei giocatori grafica
	 */
	UnoGraphicPlayerList graphicPlayersList;
	public UnoGraphicPlayerList getPlayersList() { return graphicPlayersList; } 
	
	/**
	 * Barra del menu
	 * */
	private UnoMenuBar menuBar;
	public UnoMenuBar getUnoMenuBar() { return menuBar; }

	/**
	 * Mano delle carte del giocatore
	 * */
	private HandOfCard hof;
	public HandOfCard getHof() { return hof; }
	
	/**
	 * Mazzo delle carte
	 * */
	private Deck deck;
	
	/**
	 * Pannello che mostra il colore in gioco 
	 * */
	private ColorViewer colorViewer;
	public ColorViewer getColorViewer() { return colorViewer; }


	/**
	 * lista delle carte giocate
	 * */
	private PlayedCardsList playedCardsList;


	/**
	 * */
	public Main() throws IOException{
		hof = null;
		playedCardsList = null;
		this.contentPane = new JPanel();
		Main.globalCurrentColor = null;
		// dimensioni del pannello
		setMinimumSize(new Dimension(800,600));
		setPreferredSize(new Dimension(800,600));
		setContentPane(contentPane);
		BorderLayout bl = new BorderLayout();
		bl.setVgap(20);
		contentPane.setLayout(bl);
		setTitle("crash tollerance - UNO - distributed game");
		initialize();
		
	}
	
	
	/**
	 * Inizializza i componenti della finestra.
	 * @throws IOException 
	 * */
	private void initialize() throws IOException {
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setDefaultLookAndFeelDecorated(true);
		
		// aggiunge il menù all'interfaccia
		menuBar = new UnoMenuBar(this);
		setJMenuBar(menuBar);

		BorderLayout bl = new BorderLayout();
		leftPanel = new JPanel();
		leftPanel.setLayout(bl);
		
		rightPanel = new JPanel();
		rightPanel.setBorder(BorderFactory.createLineBorder(Color.black));

		// inizializzo lo splitter
		setJSplitPane(new JSplitPane());
		getJSplitPane().setOneTouchExpandable(true);
		// a cosa serve?
		//getJSplitPane().setContinuousLayout(true);
		
		// bisogna fare in modo che non si possa ridimensionare il JSplitPane
		// OK: workaround: si fissa la dimensione della barra a 0 pixel
		// in questo modo la barra dventa "incliccabile"
		getJSplitPane().setDividerSize(0);
		
		getJSplitPane().setLeftComponent(leftPanel);
		getJSplitPane().setRightComponent(rightPanel); 
		getContentPane().add(getJSplitPane());
		
		decksContainer = new JPanel();
		leftPanel.add(decksContainer);
		//leftPanel.add(decksContainer, BorderLayout.CENTER);
		

		
		// serve a fissare la dimensione della jSplitPane ed a
		// spostarla dinamicamente ogni resize della finestra principale
		this.addComponentListener(new ComponentAdapter(){
			public void componentResized(ComponentEvent arg0) {
				try {
					// se la playersList esiste
					getJSplitPane().setDividerLocation(getWidth() - (getPlayersList().getWidth() + 20));
				} catch(Exception e) {
					// altrimenti
					// (utile solo nella fase iniziale di creazione del pannello)
					getJSplitPane().setDividerLocation(getWidth());
				}
				getJSplitPane().validate();
			}
		});
		pack();	
	}

	
	/**
	 * Aggiunge i mazzi e li visualizza
	 * */
	public void addDeck(Deck deck) {
		this.deck = deck;
		getDecksContainer().add(this.deck);
		pack();
	}
	
	
	/**
	 * Aggiunge la mano e la visualizza
	 * */	
	public void addHof(HandOfCard hof){
		this.hof = hof;
		getLeftPanel().add(hof, BorderLayout.SOUTH);
		//System.out.println("size di hof nel Main " + hof.getHOCSize());
		pack();
	}

	/**
	 * 
	 * */
	public void setPlayedCardsList(PlayedCardsList playedCardsList) {
		this.playedCardsList = playedCardsList;
		//L'aggiungo alla gui
		getDecksContainer().add(playedCardsList);
		validate();
	}
	
	/**
	 * 
	 * */
	public PlayedCardsList getPlayedCardsList() {
		return playedCardsList;
	}
	
	/**
	 * setta il colore in gioco, nel visualizzatore del colore
	 * */
	public void setColorViewer(ColorViewer colorViewer) { 
		
		this.colorViewer = colorViewer;
		Main.globalCurrentColor = colorViewer.getCurrentColorValue();
		getRightPanel().add(getColorViewer());
		validate();
		pack();
	}
	
	/**
	 * crea e popola la lista dei giocatori nell'interfaccia
	 * */
	public void createAndSetPlayersList(LinkedList<UnoPlayerID> givenPL){

		this.graphicPlayersList = new UnoGraphicPlayerList(givenPL);
		// associo lo stesso colore del JPanel
		getPlayersList().setBackground(this.getBackground());
		// aggiungo al pannello di destra la lista dei giocatori
		getRightPanel().add(this.getPlayersList());
		// compongo la finestra
		pack();
		// aggiusto la posizione dello splitter
		getJSplitPane().setDividerLocation(getWidth() - (getPlayersList().getWidth() + 20));
	}
	
	/**
	 * visualizza la finestra di gioco
	 * */
	public void startGame(){ setVisible(true); }

	
	private static void createAndShowGame() throws IOException {
		Main game = new Main();
		game.startGame();
	}

	
	/**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
	public static void main(String[] args) {		
		//Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
					createAndShowGame();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }		
        });
	}
	
}
